<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Iterator 和 for... of 循环 </title>
</head>

<body>
    <script>
        var it = makeIterator(['a', 'b'])
        console.log(it.next())
        console.log(it.next())
        console.log(it.next())

        function makeIterator(array) {
            var nextIndex = 0;
            return {
                // next: function () {
                //     return nextIndex < array.length ? {
                //         value: array[nextIndex++],
                //         done: false
                //     } : {
                //         value: undefined,
                //         done: true
                //     }
                // }
                next: () => {
                    return nextIndex < array.length ? {
                        value: array[nextIndex++],
                        done: false
                    } : {
                        value: undefined,
                        done: true
                    }
                }
            }
        }
        // 以上代码定义了一个makeIterator 函数，他是一个遍历器生成函数，作用就是返回一个遍历器函数

        // 原生具备 Iterator 接口的数据结构如下。       
        // Array
        // Map
        // Set
        // String
        // TypedArray
        // 函数的 arguments 对象
        // NodeList 对象

        // ES6 规定，默认的 Iterator 接口部署在数据结构的Symbol.iterator属性，或者说，一个数据结构只要具有Symbol.iterator属性，就可以认为是“可遍历的”
        // 。Symbol.iterator属性本身是一个函数，就是当前数据结构默认的遍历器生成函数。执行这个函数，就会返回一个遍历器。至于属性名Symbol.iterator，它是一个表达式，返回Symbol对象的iterator属性，这是一个预定义好的、类型为 Symbol 的特殊值，所以要放在方括号内（参见《Symbol》一章）。

        const obj = {
            [Symbol.iterator]: function () {
                return {
                    next: function () {
                        return {
                            value: 1,
                            done: true
                        }
                    }
                }
            }
        }

        let arr = ['a', 'b', 'c']
        let iter = arr[Symbol.iterator]()
        console.log(iter.next())
        console.log(iter.next())
        console.log(iter.next())
        console.log(iter.next())

        class Rangeiterator {
            constructor(start, stop) {
                    this.value = start
                    this.stop = stop
                }
                [Symbol.iterator]() {
                    return this
                }
            next() {
                var value = this.value
                if (value < this.stop) {
                    this.value++
                    return {
                        done: false,
                        value: value
                    }
                } else {
                    return {
                        done: true,
                        value: undefined
                    }
                }


            }
        }

        function range(start, stop) {
            return new Rangeiterator(start, stop)
        }
        for (var value of range(0, 3)) {
            console.log(value)
        }
    </script>
</body>

</html>